package org.hepeng.workx.spring.cloud.netflix.zuul.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.BooleanUtils;
import org.hepeng.workx.spring.cloud.netflix.zuul.RequestContextHelper;
import org.hepeng.workx.spring.security.web.filter.UpstreamRequestSkipOverSpringSecurityChainFilter;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @author he peng
 */
public class SecurityContextHeaderFilter extends ZuulFilter {

//    private ObjectSerializer<SecurityContext> objectSerializer;
    private RedisSerializer redisSerializer = new JdkSerializationRedisSerializer();
    private int filterOrder;
    public static final String SHOULD_FILTER_ATTR = SecurityContextHeaderFilter.class.getName() +".SHOULD_FILTER_ATTR";

    public SecurityContextHeaderFilter(int filterOrder) {
        this.filterOrder = filterOrder;
//        this.objectSerializer = ObjectSerializationUtils.newObjectSerializer(SupportSerializer.HESSIAN , SecurityContext.class);
    }

//    public SecurityContextHeaderFilter(int filterOrder , ObjectSerializer objectSerializer) {
//        this(filterOrder);
//        this.objectSerializer = objectSerializer;
//    }

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return this.filterOrder;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContextHelper.get();
        HttpServletRequest request = ctx.getRequest();
        Boolean shouldFilter = BooleanUtils.toBoolean((String) request.getAttribute(SHOULD_FILTER_ATTR));
        return shouldFilter;
    }

    @Override
    public Object run() throws ZuulException {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        if (Objects.nonNull(securityContext)) {
//            Authentication auth = securityContext.getAuthentication();
//                String headerVal = this.objectSerializer.serializeBase64String(securityContext);
            RequestContext ctx = RequestContextHelper.get();
            byte[] bytes = this.redisSerializer.serialize(securityContext);
            String headerVal = Base64.encodeBase64String(bytes);
            ctx.addZuulRequestHeader(UpstreamRequestSkipOverSpringSecurityChainFilter.SECURITY_CONTEXT_HEADER_NAME , headerVal);
//            boolean isAuthenticated = Objects.nonNull(auth)
//                    && ! AnonymousAuthenticationToken.class.isAssignableFrom(auth.getClass())
//                    && auth.isAuthenticated();
//            if (isAuthenticated) {
//                RequestContext ctx = RequestContextHelper.get();
////                String headerVal = this.objectSerializer.serializeBase64String(securityContext);
//                byte[] bytes = this.redisSerializer.serialize(securityContext);
//                String headerVal = Base64.encodeBase64String(bytes);
//                ctx.addZuulRequestHeader(UpstreamRequestSkipOverSpringSecurityChainFilter.SECURITY_CONTEXT_HEADER_NAME , headerVal);
//            }
        }
        return null;
    }
}
